home *** CD-ROM | disk | FTP | other *** search
/ Your Choice 1 / your choice.zip / your choice / PRGMMING / CX201 / CXSUB.C < prev    next >
C/C++ Source or Header  |  1994-03-01  |  7KB  |  282 lines

  1. /*
  2.    CXSUB functions.
  3.    Copyright (c) 1990-1994 Eugene Nelson, Four Lakes Computing.
  4.  
  5.    This file contains useful subroutines that may be used with Cx.
  6.    See files CXSUB.DOC and CXSUB.H for interface information.
  7. */
  8.  
  9. #include <stddef.h>
  10. #include <stdlib.h>
  11. #include <stdio.h>
  12. #include <io.h>
  13. #include <fcntl.h>
  14. #include <sys\types.h>
  15. #include <sys\stat.h>
  16.  
  17. #include "cxsub.h"
  18.  
  19. /*-----------------------------------------------------------------------*/
  20. char  *cx_error_message(
  21.          CXINT err)
  22. {
  23.    switch (err)
  24.    {
  25.       case CX_ERR_INVALID:    return ("data could not be decompressed");
  26.       case CX_ERR_METHOD:     return ("invalid compression method");
  27.       case CX_ERR_BUFFSIZE:   return ("invalid buffer size");
  28.       case CX_ERR_TEMPSIZE:   return ("invalid temp buffer size");
  29.       case CXSUB_ERR_OPENS:   return ("could not open source");
  30.       case CXSUB_ERR_OPEND:   return ("could not open destination");
  31.       case CXSUB_ERR_NOMEM:   return ("insufficient memory");
  32.       case CXSUB_ERR_READ:    return ("could not read from source");
  33.       case CXSUB_ERR_WRITE:   return ("could not write to destination");
  34.       case CXSUB_ERR_CLOSE:   return ("could not close destination");
  35.       case CXSUB_ERR_INVALID: return ("source file is invalid or corrupt");
  36.    }
  37.  
  38.    return ("unknown");
  39. }
  40.  
  41.  
  42. /*
  43.    The following define and routine
  44.    
  45.       CX_FILESUB_RET
  46.       cx_filesub_error
  47.  
  48.    Are used to release allocated memory.
  49. */
  50.  
  51.  
  52. #define CX_FILESUB_RET(n)  return(cx_filesub_error(n, ibuff, obuff, tbuff))
  53. /*----------------------------------------------------------------------*/
  54. static CXINT   cx_filesub_error(
  55.          CXINT    err,
  56.          CXBUFF   ibuff,
  57.          CXBUFF   obuff,
  58.          CXBUFF   tbuff)
  59. {
  60.    if (ibuff != NULL)      free(ibuff);
  61.    if (obuff != NULL)      free(obuff);
  62.    if (tbuff != NULL)      free(tbuff);
  63.  
  64.    return (err);
  65. }
  66.  
  67. /*----------------------------------------------------------------------*/
  68. CXINT cx_compress_ofile(
  69.          int   ofile,
  70.          int   ifile,
  71.          CXINT method,
  72.          CXINT bsize,
  73.          CXINT tsize,
  74.          int   (*callback)(void *),
  75.          void  *p)
  76. {
  77.    CXBUFF   ibuff = NULL;
  78.    CXBUFF   obuff = NULL;
  79.    CXBUFF   tbuff = NULL;
  80.  
  81.    CXINT    j, k, crc;
  82.    CXBUFF   t;
  83.  
  84.    ibuff = (CXBUFF) malloc(bsize);
  85.    obuff = (CXBUFF) malloc(bsize+CX_SLOP);
  86.    tbuff = (CXBUFF) malloc(tsize);
  87.  
  88.    if ((ibuff == NULL) || (obuff == NULL) || (tbuff == NULL))
  89.       CX_FILESUB_RET (CXSUB_ERR_NOMEM);
  90.  
  91.    while (1)
  92.    {
  93.       if (callback != NULL)
  94.          if (callback(p) != 0)
  95.             return (0);
  96.  
  97.       j = read(ifile, ibuff, bsize);
  98.       if (j == 0xffff)
  99.          CX_FILESUB_RET (CXSUB_ERR_READ);
  100.  
  101.       if (write(ofile, &j, CXINTSIZE) != CXINTSIZE)
  102.          CX_FILESUB_RET (CXSUB_ERR_WRITE);
  103.  
  104.       if (j == 0)
  105.          break;
  106.  
  107.       k = CX_COMPRESS(method, obuff, bsize, ibuff, j, tbuff, tsize);
  108.  
  109.       if (k > j)
  110.          CX_FILESUB_RET (k);
  111.  
  112.       if (write(ofile, &k, CXINTSIZE) != CXINTSIZE)
  113.          CX_FILESUB_RET (CXSUB_ERR_WRITE);
  114.          
  115.  
  116.       if (k == j)    /* if block could not be compressed */
  117.          t = ibuff;
  118.       else
  119.          t = obuff;
  120.  
  121.       crc = CX_CRC(t, k);
  122.  
  123.       if (write(ofile, &crc, CXINTSIZE) != CXINTSIZE)
  124.          CX_FILESUB_RET (CXSUB_ERR_WRITE);
  125.  
  126.       if (write(ofile, t, k) != k)
  127.          CX_FILESUB_RET (CXSUB_ERR_WRITE);
  128.    }
  129.  
  130.    CX_FILESUB_RET (0);
  131. }
  132.  
  133. /*----------------------------------------------------------------------*/
  134. CXINT cx_compress_file(
  135.          char  *dst,
  136.          char  *src,
  137.          CXINT method,
  138.          CXINT bsize,
  139.          CXINT tsize,
  140.          int   (*callback)(void *),
  141.          void  *p)
  142. {
  143.    int   ifile = -1;
  144.    int   ofile = -1;
  145.    CXINT j, k;
  146.  
  147.    if ((ifile = open(src, O_RDWR|O_BINARY, 0)) == -1)
  148.       return (CXSUB_ERR_OPENS);
  149.  
  150.    unlink(dst);
  151.    if ((ofile = open(dst, O_WRONLY|O_CREAT|O_BINARY, S_IREAD|S_IWRITE)) == -1)
  152.    {
  153.       close(ifile);
  154.       return (CXSUB_ERR_OPEND);
  155.    }
  156.  
  157.    k = cx_compress_ofile(ofile, ifile, method, bsize, tsize, callback, p);
  158.  
  159.    close(ifile);
  160.  
  161.    j = (close(ofile) == 0? 0: CXSUB_ERR_CLOSE);
  162.  
  163.    return (k==0? j: k);
  164. }
  165.       
  166. /*----------------------------------------------------------------------*/
  167. CXINT cx_decompress_ofile(
  168.          int   ofile,
  169.          int   ifile,
  170.          int   (*callback)(void *),
  171.          void  *p)
  172. {
  173.    CXBUFF   ibuff = NULL;
  174.    CXBUFF   obuff = NULL;
  175.    CXBUFF   tbuff = NULL;
  176.  
  177.    CXINT    bsize;
  178.    CXINT    j, k, crc;
  179.    CXBUFF   t;
  180.    
  181.    if ((tbuff = (CXBUFF) malloc(CX_D_MINTEMP)) == NULL)
  182.       CX_FILESUB_RET (CXSUB_ERR_NOMEM);
  183.  
  184.    bsize = 0;
  185.  
  186.    while (1)
  187.    {
  188.       if (callback != NULL)
  189.          if (callback(p) != 0)
  190.             return (0);
  191.  
  192.       if (read(ifile, &j, CXINTSIZE) != CXINTSIZE)
  193.          CX_FILESUB_RET (CXSUB_ERR_READ);
  194.  
  195.       if (j == 0)       /* This indicates the end of file */
  196.          break;
  197.  
  198.       if (bsize < j)
  199.       {
  200.          bsize = j;
  201.          ibuff = (CXBUFF) realloc(obuff, bsize+CX_SLOP);
  202.          obuff = (CXBUFF) realloc(obuff, bsize);
  203.  
  204.          if ((ibuff == NULL) || (obuff == NULL))
  205.             CX_FILESUB_RET (CXSUB_ERR_NOMEM);
  206.       }
  207.  
  208.       if (read(ifile, &k, CXINTSIZE) != CXINTSIZE)
  209.          CX_FILESUB_RET (CXSUB_ERR_READ);
  210.  
  211.       if ((k > j) || (k > bsize) || (j > bsize))
  212.          CX_FILESUB_RET (CXSUB_ERR_INVALID);
  213.  
  214.       if (read(ifile, &crc, CXINTSIZE) != CXINTSIZE)
  215.          CX_FILESUB_RET (CXSUB_ERR_READ);
  216.  
  217.       if (read(ifile, ibuff, k) != k)
  218.          CX_FILESUB_RET (CXSUB_ERR_READ);
  219.  
  220.       if (CX_CRC(ibuff, k) != crc)
  221.          CX_FILESUB_RET (CXSUB_ERR_INVALID);
  222.  
  223.  
  224.       if (j == k)    /* if block is not compressed */
  225.          t = ibuff;
  226.       else
  227.       {
  228.          k = CX_DECOMPRESS(obuff, bsize, ibuff, k, tbuff, CX_D_MINTEMP);
  229.          if (k > CX_MAX_BUFFER)
  230.             CX_FILESUB_RET (k);
  231.  
  232.          if (j != k)
  233.             CX_FILESUB_RET (CXSUB_ERR_INVALID);
  234.  
  235.          t = obuff;
  236.       }
  237.  
  238.       if (ofile != -1)
  239.          if (write(ofile, t, j) != j)
  240.             CX_FILESUB_RET (CXSUB_ERR_WRITE);
  241.    }
  242.  
  243.    CX_FILESUB_RET (0);
  244. }
  245.  
  246.  
  247. /*----------------------------------------------------------------------*/
  248. CXINT cx_decompress_file(
  249.          char  *dst,
  250.          char  *src,
  251.          int   (*callback)(void *),
  252.          void  *p)
  253. {
  254.    int      ifile = -1;
  255.    int      ofile = -1;
  256.    CXINT    k, j;
  257.    
  258.    if ((ifile = open(src, O_RDWR|O_BINARY, 0)) == -1)
  259.       return (CXSUB_ERR_OPENS);
  260.  
  261.    if (dst != NULL)
  262.    {
  263.       unlink(dst);
  264.       if ((ofile = open(dst, O_WRONLY|O_CREAT|O_BINARY, S_IREAD|S_IWRITE)) == -1)
  265.       {
  266.          close(ifile);
  267.          return (CXSUB_ERR_OPEND);
  268.       }
  269.    }
  270.  
  271.    k = cx_decompress_ofile(ofile, ifile, callback, p);
  272.  
  273.    close(ifile);
  274.  
  275.    if (dst != NULL)
  276.       j = (close(ofile) == 0? 0: CXSUB_ERR_CLOSE);
  277.    else
  278.       j = 0;
  279.  
  280.    return (k==0? j: k);
  281. }
  282.